package com.ermaosk.juc.pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

public class Post {

    static Logger logger = LoggerFactory.getLogger(Post.class);

    public static void main(String[] args) throws InterruptedException {
        MailBox mailBox = new MailBox();
        for (int i = 0; i < 3; i++) {
            Person p = new Person(mailBox);
            p.start();
        }

//        Set<Integer> allMailIds = mailBox.getAllMail();
//        logger.info("allBox {}", allMailIds);
//        for (Integer mailId : allMailIds) {
//
//            PostMan p = new PostMan(mailBox, mailId);
//            p.start();
//        }
        Thread.sleep(1000);
        for (int i = 0; i < 3; i++) {
            PostMan p = new PostMan(mailBox);
            p.start();
        }
    }
}

class PostMan extends Thread {
    Logger logger = LoggerFactory.getLogger(Person.class);

    MailBox mailBox;

    Integer id;

    PostMan(MailBox mailBox, Integer id) {
        this.mailBox = mailBox;
        this.id = id;
    }

    PostMan(MailBox mailBox) {
        this.mailBox = mailBox;
        this.id = id;
    }

    @Override
    public void run() {
//        Set<Integer> allMailIds = mailBox.getAllMail();
//        logger.info("allBox {}", allMailIds);
        for (Integer mailId : mailBox.getAllMail()) {
            MailGuardedObject mailGuardedObject = mailBox.getBox(mailId);
            mailGuardedObject.setMessage(mailGuardedObject.getId() + " hello");
        }

    }

}

class Person extends Thread {
    Logger logger = LoggerFactory.getLogger(Person.class);
    MailBox mailBox;

    Person(MailBox mailBox) {
        this.mailBox = mailBox;
    }

    @Override
    public void run() {
        MailGuardedObject guardedObject = new MailGuardedObject();
        logger.info("createbox");

        mailBox.createBox(guardedObject);
        try {
            String mail = guardedObject.get();
            logger.info("recivie mail content {}", mail);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class MailBox {
    Logger logger = LoggerFactory.getLogger(MailBox.class);

    private Map<Integer, MailGuardedObject> data = new Hashtable<>();
    private Integer id = 0;

    private Integer generateId() {
        synchronized (this) {
            id++;
            return id;
        }
    }

    public void createBox(MailGuardedObject mailGuardedObject) {
        Integer id = generateId();
        logger.info("createbox...{}", id);

        data.put(id, mailGuardedObject);
    }

    public MailGuardedObject getBox(Integer id) {
        return data.remove(id);
    }

    public Set<Integer> getAllMail() {
        return data.keySet();
    }
}

class MailGuardedObject {

    Integer id;

    String mailContent;

    public Integer getId() {
        return id;
    }

    public void setMessage(String msg) {
        synchronized (this) {
            this.mailContent = msg;
            this.notifyAll();
        }

    }

    public String get() throws InterruptedException {
        synchronized (this) {
            if (this.mailContent == null) {
                this.wait();
            }
            return mailContent;
        }
    }
}

